package com.smartian.scan.filesearch.bean;

import android.text.TextUtils;

import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StringPath {
    /**
     * 支持正则，正则表达式中不支持
     */
    public static final String REGEXP_SEPARATOR = "//";
    public static final String REGEXP_CONTENT_PROVIDER = "content://";
    public static final String REGEXP_LOCAL_FILES = "file://";
    public static final String REGEXP_FILENAME_SEPARATOR = "/+/";
    private static final Map<String, Pattern> REGEXP_PATTERN_POOL = new ConcurrentHashMap<String, Pattern>();

    public String fullPath;
    private String folderPath;//rootPath + regexPath
    private String rootPath;//根路径，不包括正则
    private String regexPath;//根路径后的正则路径
    private String regexName;//包含正则的文件名

    public StringPath(String fullPath) {
        this.fullPath = fullPath;
        this.initPath();
    }

    private void initPath() {
        if (TextUtils.isEmpty(fullPath)) {
            return;
        }

        if (fullPath.startsWith(REGEXP_CONTENT_PROVIDER)) {
            this.rootPath = this.fullPath;
            return;
        }
        if (fullPath.startsWith(REGEXP_LOCAL_FILES)) {
            this.fullPath = this.fullPath.substring(REGEXP_LOCAL_FILES.length());
        }

        final int fileIndex = fullPath.indexOf(REGEXP_FILENAME_SEPARATOR);

        try {
            if (fileIndex != -1) {
                folderPath = fullPath.substring(0, fileIndex);
                regexName = fullPath.substring(fileIndex + REGEXP_FILENAME_SEPARATOR.length());
            } else {
                folderPath = fullPath;
            }

            final int regexIndex = folderPath.indexOf(REGEXP_SEPARATOR);
            if (regexIndex != -1) {
                rootPath = folderPath.substring(0, regexIndex);
                regexPath = folderPath.substring(regexIndex + REGEXP_SEPARATOR.length());

                if (!TextUtils.isEmpty(regexName)) {
                    rootPath = folderPath.substring(0, rootPath.lastIndexOf(REGEXP_FILENAME_SEPARATOR + regexName));
                }
            } else {
                rootPath = folderPath;
            }
        } catch (Exception e) {
            folderPath = null;
            rootPath = null;
            regexPath = null;
            regexName = null;
        }


    }

    public String getFolderPath() {
        return folderPath;
    }


    public String getRootPath() {
        return rootPath;
    }

    public String getRegexPath() {
        return regexPath;
    }

    public String getRegexName() {
        return regexName;
    }

    public String getFullPath() {
        return fullPath;
    }

    public static Pattern getRegExpPattern(String regExpFileName) {

        try {
            Pattern pattern = REGEXP_PATTERN_POOL.get(regExpFileName);
            if (pattern == null) {
                pattern = Pattern.compile(regExpFileName);
                REGEXP_PATTERN_POOL.put(regExpFileName, pattern);
            }
            return pattern;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static boolean isNotMatchFilePath(String regExpPath, String rootPath, PathFile file) {
        if (TextUtils.isEmpty(regExpPath)) {
            return false;
        }

        Pattern pattern = StringPath.getRegExpPattern(rootPath + File.separator + regExpPath);
        if (pattern == null) {
            return true;
        }
        Matcher matcher = pattern.matcher(file.getName());
        if (matcher == null || !matcher.find()) {
            return true;
        }

        String prefix = matcher.group();
        if (!TextUtils.isEmpty(prefix)) {
            return true;
        }

        String path = file.getAbsolutePath();
        if (!path.startsWith(prefix)) {
            return true;
        }

        return false;
    }

    public static boolean isNotMatchFileName(String regExpFileName, PathFile file) {
        if (TextUtils.isEmpty(regExpFileName)) {
            return false;
        }
        Pattern pattern = StringPath.getRegExpPattern(regExpFileName);
        if (pattern == null) {
            return true;
        }
        if (!pattern.matcher(file.getName()).matches()) {
            return true;
        }
        return false;
    }


    public static SearchResult transform(SearchResult scanResult, StringPath stringPath) {
        if (scanResult == null || stringPath == null) {
            return scanResult;
        }
        List<PathFile> files = scanResult.getFiles();
        List<PathFile> dirs = scanResult.getDirs();

        String regExpFileName = stringPath.getRegexName();
        String regExpPath = stringPath.getRegexPath();
        String rootPath = stringPath.getRootPath();

        if (files != null) {
            List<PathFile> filterFiles = transformFiles(files, regExpFileName, regExpPath, rootPath);
            scanResult.setFiles(filterFiles);
        }
        if (dirs != null) {
            List<PathFile> filterDirs = transformDirs(dirs, regExpPath, rootPath);
            scanResult.setDirs(filterDirs);
        }

        return scanResult;

    }

    private static List<PathFile> transformDirsWithoutRegExp(List<PathFile> dirs) {
        if (dirs == null) return dirs;
        for (PathFile pathFile : dirs) {
            StringPath stringPath = pathFile.getStringPath();
            stringPath.resetPath(pathFile.getAbsolutePath(), null, null);
        }
        return dirs;
    }

    private static List<PathFile> transformDirs(List<PathFile> dirs, String regExpPath, String rootPath) {

        if (TextUtils.isEmpty(regExpPath)) {
            return transformDirsWithoutRegExp(dirs);
        }
        String[] pathRegExpFragments = regExpPath.split(File.separator);
        if (pathRegExpFragments == null || pathRegExpFragments.length == 0) {
            return transformDirsWithoutRegExp(dirs);
        }
        String subRootRegExp = rootPath + pathRegExpFragments[0];
        Pattern pattern = getRegExpPattern(subRootRegExp);
        Iterator<PathFile> iterator = dirs.iterator();
        do {
            if (!iterator.hasNext()) {
                break;
            }
            PathFile pathFile = iterator.next();
            String subDirPath = findSubDirPath(pattern, pathFile);
            if (TextUtils.isEmpty(subDirPath)) {
                iterator.remove();
                continue;
            }
            resetStringPath(pathFile, pathRegExpFragments);
        } while (true);

        return dirs;
    }

    private static void resetStringPath(PathFile pathFile, String[] pathRegExpFragments) {
        StringPath stringPath = pathFile.getStringPath();
        String regExPath = null;
        if (pathRegExpFragments == null || pathRegExpFragments.length <= 1) {
            regExPath = null;
        } else {
            StringBuilder pathBuilder = new StringBuilder();
            for (int i = 1; i < pathRegExpFragments.length; i++) {
                pathBuilder.append(pathRegExpFragments[i]);
                if (i < pathRegExpFragments.length - 1) {
                    pathBuilder.append(File.separator);
                }
            }
            regExPath = pathBuilder.toString();
        }
        stringPath.resetPath(pathFile.getAbsolutePath(), regExPath, stringPath.getRegexName());
    }

    private void resetPath(String rootPath, String regexPath, String regexName) {

        StringBuilder stringBuilder = new StringBuilder(rootPath);
        if (!TextUtils.isEmpty(regexPath)) {
            stringBuilder.append(REGEXP_SEPARATOR).append(regexPath);
        }
        if (!TextUtils.isEmpty(regexName)) {
            stringBuilder.append(REGEXP_FILENAME_SEPARATOR).append(regexName);
        }
        this.setFullPath(stringBuilder.toString());
        this.initPath();
    }

    private void setFullPath(String fullPath) {
        this.fullPath = fullPath;
    }


    private static String findSubDirPath(Pattern pattern, PathFile file) {
        if (null == pattern) {
            return null;
        }
        String absolutePath = file.getAbsolutePath();
        Matcher matcher = pattern.matcher(absolutePath);

        if (matcher == null || !matcher.find()) {
            return null;
        }
        String prefix = matcher.group();
        if (!TextUtils.isEmpty(prefix)) {
            return null;
        }
        String path = file.getAbsolutePath();

        if (!path.startsWith(prefix)) {
            return null;
        }
        return path;
    }

    public static List<PathFile> transformFiles(List<PathFile> files, String regExpFileName, String regExpPath, String rootPath) {

        if (TextUtils.isEmpty(regExpFileName)) {
            return files;
        }
        Iterator<PathFile> iterator = files.iterator();
        do {
            if (!iterator.hasNext()) {
                break;
            }
            PathFile file = iterator.next();
            if (isNotMatchFileName(regExpFileName, file)) {
                iterator.remove();
                continue;
            }

            if (isNotMatchFilePath(regExpPath, rootPath, file)) {
                iterator.remove();
                continue;
            }
        } while (true);

        return files;
    }
}
